import os
import argparse
from urllib.parse import quote_plus as urlquote

from dotenv import load_dotenv
from functools import lru_cache
from pydantic import Field
from pydantic_settings import BaseSettings


# 设置时区
os.environ['TZ'] = os.getenv('TIMEZONE', 'PRC')
# 项目目录
BASE_DIR: str = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# logger.info(f'BASE_DIR: {BASE_DIR}')


class AppConfigSettings(BaseSettings):
    # 环境变量
    app_env: str = Field(env='APP_ENV', default='')
    app_debug: str = Field(env='APP_DEBUG', default=False)

    # 应用名称
    app_name: str = Field(default='SanRen.Work', env='APP_NAME')
    app_version: str = Field(env='APP_VERSION', default='1.0.0')
    app_ui_version: str = Field(env='APP_UI_VERSION', default='1.0.0')

    # 时区
    timezone: str = Field(env='TIMEZONE', default='Asia/Shanghai')

    # 启动参数
    app_host: str = Field(env='APP_HOST', default='0.0.0.0')
    app_port: int = Field(env='APP_PORT', default=10008)
    app_reload: bool = Field(env='APP_RELOAD', default=True)

    # 目录信息
    base_path: str = BASE_DIR
    log_path: str = os.path.join(BASE_DIR, 'logs')
    storage_path: str = os.path.join(BASE_DIR, 'storage')
    upload_path: str = os.path.join(storage_path, 'uploads')
    export_path: str = os.path.join(storage_path, 'exports')

    # 日志配置
    log_rotation: str = Field(env='LOG_ROTATION', default='00:00')  # 每天午夜轮转
    log_retention: str = Field(env='LOG_RETENTION', default='30 days')  # 保留30天
    log_compression: str = Field(env='LOG_COMPRESSION', default='zip')  # 压缩格式

    # 数据库 默认连接
    db_default: str = Field(default='mysql', env='DB_DEFAULT')

    # 数据库配置
    db_type: str = Field(default='mysql', env='DB_TYPE')
    db_host: str = Field(default='127.0.0.1', env='DB_HOST')
    db_port: int = Field(default=3306, env='DB_PORT')
    db_user: str = Field(default='root', env='DB_USER')
    db_pass: str = Field(default='root', env='DB_PASS', hide_input=True)
    db_name: str = Field(default='sanren', env='DB_NAME')
    db_prefix: str = Field(default='san_', env='DB_PREFIX')
    db_charset: str = Field(default='utf8mb4', env='DB_CHARSET')
    db_log: bool = Field(env='DB_LOG', default=True)

    @property
    def db_url(self):
        """ 格式化数据库 url """
        if self.db_type == 'mysql':
            return f'mysql+pymysql://{self.db_user}:{urlquote(self.db_pass)}@{self.db_host}:{self.db_port}/{self.db_name}?charset={self.db_charset}'
        elif self.db_type == 'postgres':
            return f'postgresql://{self.db_user}:{urlquote(self.db_pass)}@{self.db_host}:{self.db_port}/{self.db_name}'

    # 码库 数据库配置
    db_code_type: str = Field(default='mysql', env='DB_CODE_TYPE')
    db_code_host: str = Field(default='127.0.0.1', env='DB_CODE_HOST')
    db_code_port: int = Field(default=3306, env='DB_CODE_PORT')
    db_code_user: str = Field(default='root', env='DB_CODE_USER')
    db_code_pass: str = Field(default='root', env='DB_CODE_PASS', hide_input=True)
    db_code_name: str = Field(default='sanren', env='DB_CODE_NAME')
    db_code_prefix: str = Field(default='san_', env='DB_CODE_PREFIX')
    db_code_charset: str = Field(default='utf8mb4', env='DB_CODE_CHARSET')
    db_code_log: bool = Field(env='DB_CODE_LOG', default=True)

    @property
    def db_code_url(self):
        """ 格式化码库数据库 url """
        if self.db_code_type == 'mysql':
            return f'mysql+pymysql://{self.db_code_user}:{urlquote(self.db_code_pass)}@{self.db_code_host}:{self.db_code_port}/{self.db_code_name}?charset={self.db_code_charset}'
        elif self.db_code_type == 'postgres':
            return f'postgresql://{self.db_code_user}:{urlquote(self.db_code_pass)}@{self.db_code_host}:{self.db_code_port}/{self.db_code_name}'

    # Redis 配置
    redis_host: str = Field(default='127.0.0.1', env='REDIS_HOST')
    redis_auth: str = Field(default='', env='REDIS_AUTH', hide_input=True)
    redis_port: int = Field(default=6379, env='REDIS_PORT')
    redis_db: int = Field(default=0, env='REDIS_DB')

    @property
    def redis_url(self):
        """ 格式化 Redis url """
        return f'redis://:{urlquote(self.redis_auth)}@{self.redis_host}:{self.redis_port}/{self.redis_db}'

    # CORS Config
    cors_allow_origins: list = ['*']
    cors_allow_credentials: bool = True
    cors_allow_methods: list = [
        'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'
    ]
    cors_allow_headers: list = ['*']

    # token url
    token_url: str = '/api/auth/token'

    # JWT 密码
    # to get a string like this run:
    # openssl rand -hex 32
    # SECRET_KEY 记得保密生产环境 不要直接写在代码里面
    secret_key: str = Field(default='LG#B@2022-*0326~chris-xu', env='SECRET_KEY', hide_input=True)
    algorithm: str = Field(default='HS256', env='ALGORITHM')
    # token 过期时间 60 minutes * 24 hours * 8 days = 8 days
    access_token_expire_minutes: int = Field(default=60 * 24 * 1, env='ACCESS_TOKEN_EXPIRE_MINUTES')
    # 验证码有效时间
    captcha_expire_second: int = Field(default=180, env='CAPTCHA_EXPIRE_SECOND')

    # 节点信息
    node_code: str = Field(default='', env='NODE_CODE')
    first_customer_id: str = Field(default='20000001', env='FIRST_CUSTOMER_ID')
    web_host: str = Field(default='', env='WEB_HOST')

    # 总后台配置
    zht_api_url: str = Field(default='http://localhost:10008/', env='ZHT_API_URL')
    zht_api_userinfo_url: str = Field(default='/api/profile/', env='ZHT_API_USERINFO_URL')
    zht_api_token_verify_url: str = Field(default='/api/token/verify', env='ZHT_API_TOKEN_VERIFY_URL')

    # DING BOG
    ding_bot_token: str = Field(default='', env='DING_BOT_TOKEN')

    # 异步任务 Redis 库
    async_redis_host: str = Field(default='127.0.0.1', env='ASYNC_REDIS_HOST')
    async_redis_auth: str = Field(default='', env='ASYNC_REDIS_AUTH', hide_input=True)
    async_redis_port: int = Field(default=6379, env='ASYNC_REDIS_PORT')
    async_redis_db: int = Field(default=1, env='ASYNC_REDIS_DB')

    # 文件存储系统类型 默认本地
    FILESYSTEM_TYPE: str = Field(default='local', env='FILESYSTEM_TYPE')

    # OSS
    oss_endpoint: str = Field(default='', env='OSS_ENDPOINT')
    oss_access_key_id: str = Field(default='', env='OSS_ACCESS_KEY_ID')
    oss_access_key_secret: str = Field(default='', env='OSS_ACCESS_KEY_SECRET')
    oss_bucket_name: str = Field(default='', env='OSS_BUCKET_NAME')
    oss_domain: str = Field(default='', env='OSS_DOMAIN')

    # 七牛云
    qiniu_access_key: str = Field(default='', env='QINIU_ACCESS_KEY')
    qiniu_secret_key: str = Field(default='', env='QINIU_SECRET_KEY')
    qiniu_bucket: str = Field(default='', env='QINIU_BUCKET')
    qiniu_domain: str = Field(default='', env='QINIU_DOMAIN')

    # 文件系统目前缀
    file_prefix: str = Field(default='uploads', env='FILE_PREFIX')


@lru_cache
def getAppConfig() -> AppConfigSettings:
    load_dotenv(os.path.join(BASE_DIR, '.env'), override=True)

    return AppConfigSettings()


appSettings = getAppConfig()

__all__ = ['appSettings']
